package xj.graph2d.template;

import java.util.Map;

import xj.graph2d.DrawShapeConstants;
import xj.graph2d.LineShape;
import xj.graph2d.TextShape;
import xj.graph2d.shapes.BoxLabel;
import xj.graph2d.shapes.GraphEdgeShape;
import xj.graph2d.shapes.PolyLineShape;
import xj.graph2d.shapes.OrthogonalLineShape;
import xj.graph2d.shapes.uml.PackageShape;
import xj.graph2d.shapes.uml.UMLUtil;
import xj.graph2d.template.uml.UMLPackageModelListener;
import xj.model.uml.UMLAssociation;
import xj.model.uml.UMLPackage;

public class UMLPackageDiagramTemplate 
  extends UMLClassDiagramTemplate {

  // Package Diagram

  static String[][] packageNodeEdgeToolNames = {
    // TOP_SIDE
    { "Realization1-Popup" },

    // BOTTOM_SIDE 
    { "Realization2-Popup" },

    // LEFT_SIDE
    { "Dependency1-Popup", "Dependency2-Popup", }, 

    // RIGHT_SIDE
    { "Dependency3-Popup", "Dependency4-Popup", }, 

  };

  static String[][] packageDiagramGapToolNames = {
    { "Package2", "Package1", "Class", },
  };

  static String[] realizationEdgeShapeNames = {
    "Realization-Shape1", 
    "Realization-Shape2", 
    "Realization-Shape3", 
    "Realization-Shape4", 
    "Realization-Shape5", 
  };

  static String[] dependencyEdgeShapeNames = {
    "Dependency-Shape1", 
    "Dependency-Shape2", 
    "Dependency-Shape3", 
    "Dependency-Shape4", 
    "Dependency-Shape5", 
  };

  public UMLPackageDiagramTemplate() {
  }

  @Override
  public void initTools() {
    addNodeToolNames(name + ".Package1", packageNodeEdgeToolNames);
    addNodeToolNames(name + ".Package2", packageNodeEdgeToolNames);

    String[] depTemp = { ".Dependency1", ".Dependency2", ".Dependency3" };     
    for (int i = 0; i < depTemp.length; i++) { 
      addEdgeToolNames(name + depTemp[i], dependencyEdgeShapeNames);
    }

    addEdgeToolNames(name + ".Realization", realizationEdgeShapeNames);
  }

  @Override
  public String[][] getGapToolNames() { 
    return packageDiagramGapToolNames;
  }

  @Override
  public void makeTemplate(Map iconMap) {

    // package
    addPackageTemplate("Package1", true, 100, 45, 40, 10);
    addPackageTemplate("Package2", false, 200, 150, 70, 20);

    // class
    addClassTemplate("Class", true, false, false, 100, 30, iconMap);

    // dependency
    GraphEdgeShape line = new GraphEdgeShape(0, 20, 50, 20);
    LineShape line1 = new LineShape(0, 20, 50, 20);
    addDependencyTemplate("Dependency1", line, line1, 
			  UMLAssociation.AssociationType.Dependency,
			  PACKAGE_DEPENDENCY_COLOR);

    GraphEdgeShape oedge = new GraphEdgeShape(true, 0, 80);
    oedge.addPoint(100, 20);
    oedge.calculateBounds();
    OrthogonalLineShape oline = new OrthogonalLineShape(0, 80);
    oline.addPoint(100, 20);
    oline.calculateBounds();
    addDependencyTemplate("Dependency2", oedge, oline, 
			  UMLAssociation.AssociationType.Dependency,
			  PACKAGE_DEPENDENCY_COLOR);

    oedge = new GraphEdgeShape(false, 0, 80);
    oedge.addPoint(80, 0);
    oedge.calculateBounds();
    oline = new OrthogonalLineShape(false, 0, 80);
    oline.addPoint(80, 0);
    oline.calculateBounds();
    addDependencyTemplate("Dependency3", oedge, oline, 
			  UMLAssociation.AssociationType.Dependency,
			  PACKAGE_DEPENDENCY_COLOR);

    // realization
    line = new GraphEdgeShape(0, 20, 50, 20);
    line1 = new LineShape(0, 20, 50, 20);
    addGeneralizationTemplate("Realization", line, line1, 36, 24,
			      true, PACKAGE_REALIZATION_COLOR);

    // notes
    addNotesTemplate("Notes1", true, "Link");
    addNotesTemplate("Notes2", false);

    // link
    addNotesLinkTemplate("Link", new LineShape(0, 20, 50, 20));

    makeNodeEdgePopupTemplates();
    makeEdgeShapeTemplates();
  }

  protected void makeNodeEdgePopupTemplates() {
    LineShape line1 = new LineShape(0, 10, 40, 10, true);
    addDependencyTemplate("Dependency1-Popup", "Dependency1", line1, 25, 10, true,
			  PACKAGE_DEPENDENCY_COLOR, TemplateToolButton.POPUP_BUTTON);
    line1 = new LineShape(40, 10, 0, 10, true);
    addDependencyTemplate("Dependency2-Popup", "Dependency1", line1, 25, 10, false,
			  PACKAGE_DEPENDENCY_COLOR, TemplateToolButton.POPUP_BUTTON);

    line1 = new LineShape(0, 10, 40, 10, true);
    addDependencyTemplate("Dependency3-Popup", "Dependency1", line1, 25, 10, false,
			  PACKAGE_DEPENDENCY_COLOR, TemplateToolButton.POPUP_BUTTON);
    line1 = new LineShape(40, 10, 0, 10, true);
    addDependencyTemplate("Dependency4-Popup", "Dependency1", line1, 25, 10, true,
			  PACKAGE_DEPENDENCY_COLOR, TemplateToolButton.POPUP_BUTTON);

    line1 = new LineShape(10, 40, 10, 0);
    addGeneralizationTemplate("Realization1-Popup", "Realization", line1, 16, 20, true, false,
			      PACKAGE_REALIZATION_COLOR, TemplateToolButton.POPUP_BUTTON);
    line1 = new LineShape(10, 40, 10, 0);
    addGeneralizationTemplate("Realization2-Popup", "Realization", line1, 16, 20, true, true, 
			      PACKAGE_REALIZATION_COLOR, TemplateToolButton.POPUP_BUTTON);  


  }

  protected void makeEdgeShapeTemplates() { 
    // dependency 
    LineShape line = new LineShape(0, 10, 100, 10);
    addDependencyShapeTemplate("Dependency-Shape1", line, PACKAGE_DEPENDENCY_COLOR, 25, 10);
    
    PolyLineShape pline = new PolyLineShape(0, 20);
    pline.addPoint(30, 40);
    pline.addPoint(70, 0);
    pline.addPoint(100, 20);
    addDependencyShapeTemplate("Dependency-Shape2", pline, PACKAGE_DEPENDENCY_COLOR, 25, 10);

    OrthogonalLineShape oline = new OrthogonalLineShape(0, 0);
    oline.addPoint(40, 40);
    oline.addPoint(100, 0);
    oline.calculateBounds();
    addDependencyShapeTemplate("Dependency-Shape3", oline, PACKAGE_DEPENDENCY_COLOR, 25, 10);

    oline = new OrthogonalLineShape(0, 40);
    oline.addPoint(100, 5);
    oline.calculateBounds();
    addDependencyShapeTemplate("Dependency-Shape4", oline, PACKAGE_DEPENDENCY_COLOR, 25, 10);

    oline = new OrthogonalLineShape(false, 0, 40);
    oline.addPoint(50, 20);
    oline.addPoint(100, 0);
    oline.calculateBounds();
    addDependencyShapeTemplate("Dependency-Shape5", oline, PACKAGE_DEPENDENCY_COLOR, 25, 10);

    // realization 
    line = new LineShape(0, 10, 100, 10);
    addGeneralizationShapeTemplate("Realization-Shape1", line, true, PACKAGE_REALIZATION_COLOR, 25, 10);
    
    pline = new PolyLineShape(0, 20);
    pline.addPoint(30, 40);
    pline.addPoint(70, 0);
    pline.addPoint(100, 20);
    addGeneralizationShapeTemplate("Realization-Shape2", pline, true, PACKAGE_REALIZATION_COLOR, 25, 10);

    oline = new OrthogonalLineShape(0, 0);
    oline.addPoint(40, 40);
    oline.addPoint(100, 0);
    oline.calculateBounds();
    addGeneralizationShapeTemplate("Realization-Shape3", oline, true, PACKAGE_REALIZATION_COLOR, 25, 10);

    oline = new OrthogonalLineShape(0, 40);
    oline.addPoint(100, 5);
    oline.calculateBounds();
    addGeneralizationShapeTemplate("Realization-Shape4", oline, true, PACKAGE_REALIZATION_COLOR, 25, 10);

    oline = new OrthogonalLineShape(false, 0, 40);
    oline.addPoint(50, 20);
    oline.addPoint(100, 0);
    oline.calculateBounds();
    addGeneralizationShapeTemplate("Realization-Shape5", oline, true, PACKAGE_REALIZATION_COLOR, 25, 10);
  }

  protected void addPackageTemplate(String tempName, boolean leaf, 
				    float mw, float mh, float tw, float th) {
    addPackageTemplate(tempName, leaf, mw, mh, tw, th, null);
  }

  protected void addPackageTemplate(String tempName, boolean leaf, 
				    float mw, float mh, float tw, float th, 
				    Map iconMap) {
    PackageShape iconShape = new PackageShape(0, 0, mw, mh, tw, th); 
    setNodeAttr(iconShape);
    setNodeColor(iconShape, PACKAGE_FG, PACKAGE_BG);

    PackageShape tshape = new PackageShape(0, 0, mw, mh, tw, th, leaf); 
    setNodeAttr(tshape);
    setNodeColor(tshape, PACKAGE_FG, PACKAGE_BG);
    // TextShape text = makeTitleText("package", PACKAGE_NAME_FONT,
    // PACKAGE_NAME_COLOR);
    // tshape.setLabel(leaf ? DrawShape.ROLE_NODE_LABEL :
    // DrawShape.ROLE_NODE_TITLE_LABEL, text);

    TextShape stereotype = makeContentText(null, "stereotype", "\u00AB", "\u00BB", 
					   true, STEREOTYPE_FONT, STEREOTYPE_COLOR);
    stereotype.setDisplayName("Stereotypes");

    BoxLabel header;
    if (useIconInLabel() && iconMap != null) {
      BoxLabel label = makeTitleLabel("package", iconMap, PACKAGE_NAME_FONT,
				      PACKAGE_NAME_COLOR);
      header = UMLUtil.makeHeader(label, stereotype);
    } else {
      TextShape text = makeTitleText("package", PACKAGE_NAME_FONT,
				     PACKAGE_NAME_COLOR);
      text.setDisplayName("Package name");
      header = UMLUtil.makeHeader(text, stereotype);
    }
    tshape.setLabel(leaf ? DrawShapeConstants.ROLE_NODE_LABEL
		    : DrawShapeConstants.ROLE_NODE_TITLE_LABEL, header);

    tshape.setDisplayName("Package");
    tshape.setAcceptSubshape(!leaf);
    tshape.setLeaf(leaf);
    tshape.setScaleMode(DrawShapeConstants.SCALE_EXCLUDE_SUBSHAPE);

    tshape.setModel(new UMLPackage());
    tshape.setModelListener(new UMLPackageModelListener());
    // tshape.setLabelListener(new ModelLabelListener());

    int iconWidth = 36, iconHeight; 
    if (leaf) { 
      iconHeight = 16; 
    } else { 
      iconHeight = 30; 
    }
    add(new TemplateToolButton(tempName, tshape, iconShape, iconWidth, iconHeight, false, true));
  }

  // keys in styleOptions
  // package style
  public static final String PACKAGE_BG = "template.UMLPackageDiagram.Package.bg";

  public static final String PACKAGE_FG = "template.UMLPackageDiagram.Package.fg";

  public static final String PACKAGE_DEPENDENCY_COLOR = "template.UMLPackageDiagram.Dependency.color";

  public static final String PACKAGE_REALIZATION_COLOR = "template.UMLPackageDiagram.Realization.color";

  public static final String PACKAGE_NAME_FONT = "template.UMLPackageDiagram.PackageName.font";

  public static final String PACKAGE_NAME_COLOR = "template.UMLPackageDiagram.PackageName.color";

}
